<template>
  <div class="skill-cloud-container" ref="cloudContainer">
    <canvas ref="cloudCanvas" class="skill-cloud-canvas"></canvas>
  </div>
</template>

<script>
export default {
  name: 'SkillCloud',
  props: {
    skills: {
      type: Array,
      required: true
    },
    radius: {
      type: Number,
      default: 250
    },
    maxSpeed: {
      type: Number,
      default: 25
    },
    initSpeed: {
      type: Number,
      default: 50
    },
    direction: {
      type: Number,
      default: 135
    },
    keepRolling: {
      type: Boolean,
      default: true
    },
    useGradient: {
      type: Boolean,
      default: true
    },
    backgroundColor: {
      type: String,
      default: 'transparent' 
    },
    autoResize: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      points: [],
      balls: [],
      canvas: null,
      ctx: null,
      depth: 200,
      isPaused: false,
      isRunning: false,
      animationId: null,
      mouseX: 0,
      mouseY: 0,
      isMouseOver: false,
      lastTimestamp: 0
    }
  },
  mounted() {
    this.init();
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    this.stop();
    window.removeEventListener('resize', this.handleResize);
  },
  methods: {
    init() {
      this.canvas = this.$refs.cloudCanvas;
      this.ctx = this.canvas.getContext('2d');
      
      this.setCanvasSize();
      this.createBalls();
      this.start();
      
      // 添加交互事件
      const container = this.$refs.cloudContainer;
      container.addEventListener('mousemove', this.handleMouseMove);
      container.addEventListener('mouseenter', this.handleMouseEnter);
      container.addEventListener('mouseleave', this.handleMouseLeave);
    },
    
    setCanvasSize() {
      const container = this.$refs.cloudContainer;
      this.canvas.width = container.offsetWidth;
      this.canvas.height = container.offsetHeight;
    },
    
    handleResize() {
      if (this.autoResize) {
        this.stop();
        this.setCanvasSize();
        this.createBalls();
        this.start();
      }
    },
    
    handleMouseMove(e) {
      const rect = this.canvas.getBoundingClientRect();
      this.mouseX = e.clientX - rect.left;
      this.mouseY = e.clientY - rect.top;
    },
    
    handleMouseEnter() {
      this.isMouseOver = true;
    },
    
    handleMouseLeave() {
      this.isMouseOver = false;
    },
    
    createBalls() {
      this.balls = [];
      
      // 计算球面分布点
      // 根据黄金角分布算法创建点
      const count = this.skills.length;
      const phi = Math.PI * (3 - Math.sqrt(5)); // 黄金角
      
      for (let i = 0; i < count; i++) {
        const y = 1 - (i / (count - 1)) * 2; // y从1到-1
        const radius = Math.sqrt(1 - y * y); // 半径在xz平面
        
        const theta = phi * i; // 黄金角旋转
        
        const x = Math.cos(theta) * radius;
        const z = Math.sin(theta) * radius;
        
        this.balls.push({
          skill: this.skills[i],
          x: x * this.radius,
          y: y * this.radius,
          z: z * this.radius,
          originalX: x * this.radius,
          originalY: y * this.radius,
          originalZ: z * this.radius,
          opacity: 0,
          textSize: 0,
          mouseDist: 0
        });
      }
    },
    
    start() {
      if (this.isRunning) return;
      
      this.isRunning = true;
      this.lastTimestamp = performance.now();
      this.update();
    },
    
    stop() {
      this.isRunning = false;
      if (this.animationId) {
        cancelAnimationFrame(this.animationId);
        this.animationId = null;
      }
    },
    
    update() {
      if (!this.isRunning) return;
      
      this.animationId = requestAnimationFrame(() => {
        const now = performance.now();
        const delta = (now - this.lastTimestamp) / 1000; // 秒
        this.lastTimestamp = now;
        
        this.draw(delta);
        this.update();
      });
    },
    
    draw(delta) {
      if (!this.ctx) return;
      
      // 清除画布
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      
      // 填充背景
      if (this.backgroundColor !== 'transparent') {
        this.ctx.fillStyle = this.backgroundColor;
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      }
      
      const centerX = this.canvas.width / 2;
      const centerY = this.canvas.height / 2;
      
      // 自动旋转
      if (this.keepRolling && !this.isMouseOver) {
        const speed = this.maxSpeed * delta;
        const angleX = speed * 0.05;
        const angleY = speed * 0.07;
        
        for (const ball of this.balls) {
          // 绕Y轴旋转
          const cosY = Math.cos(angleY);
          const sinY = Math.sin(angleY);
          const tempX = ball.x * cosY - ball.z * sinY;
          const tempZ = ball.z * cosY + ball.x * sinY;
          ball.x = tempX;
          ball.z = tempZ;
          
          // 绕X轴旋转
          const cosX = Math.cos(angleX);
          const sinX = Math.sin(angleX);
          const tempY = ball.y * cosX - ball.z * sinX;
          const newZ = ball.z * cosX + ball.y * sinX;
          ball.y = tempY;
          ball.z = newZ;
        }
      }
      
      // 鼠标交互
      if (this.isMouseOver) {
        const mouseXFromCenter = this.mouseX - centerX;
        const mouseYFromCenter = this.mouseY - centerY;
        const distance = Math.sqrt(mouseXFromCenter * mouseXFromCenter + mouseYFromCenter * mouseYFromCenter);
        
        if (distance > 0) {
          const speed = Math.min(distance / 20, this.maxSpeed) * delta;
          const angleX = -mouseYFromCenter / distance * speed * 0.2;
          const angleY = mouseXFromCenter / distance * speed * 0.2;
          
          for (const ball of this.balls) {
            // 绕Y轴旋转
            const cosY = Math.cos(angleY);
            const sinY = Math.sin(angleY);
            const tempX = ball.x * cosY - ball.z * sinY;
            const tempZ = ball.z * cosY + ball.x * sinY;
            ball.x = tempX;
            ball.z = tempZ;
            
            // 绕X轴旋转
            const cosX = Math.cos(angleX);
            const sinX = Math.sin(angleX);
            const tempY = ball.y * cosX - ball.z * sinX;
            const newZ = ball.z * cosX + ball.y * sinX;
            ball.y = tempY;
            ball.z = newZ;
            
            // 计算与鼠标的距离
            const ballScreenX = centerX + ball.x * this.getScale(ball.z);
            const ballScreenY = centerY + ball.y * this.getScale(ball.z);
            const dx = this.mouseX - ballScreenX;
            const dy = this.mouseY - ballScreenY;
            ball.mouseDist = Math.sqrt(dx * dx + dy * dy);
          }
        }
      } else {
        // 重置鼠标距离
        for (const ball of this.balls) {
          ball.mouseDist = 0;
        }
      }
      
      // 对球进行深度排序
      this.balls.sort((a, b) => b.z - a.z);
      
      // 绘制球
      for (const ball of this.balls) {
        const scale = this.getScale(ball.z);
        const x = centerX + ball.x * scale;
        const y = centerY + ball.y * scale;
        
        // 计算不透明度和文字大小
        ball.opacity = this.getOpacity(ball.z);
        ball.textSize = this.getTextSize(ball.z);
        
        // 绘制文本
        if (ball.opacity > 0.1) {
          this.ctx.globalAlpha = ball.opacity;
          this.ctx.font = `${ball.textSize}px Arial, sans-serif`;
          this.ctx.textAlign = 'center';
          this.ctx.textBaseline = 'middle';
          
          // 根据鼠标距离调整颜色
          if (this.useGradient && this.isMouseOver && ball.mouseDist < 100) {
            // 距离越近颜色越明亮
            const intensity = 1 - Math.min(ball.mouseDist / 100, 1);
            this.ctx.fillStyle = this.getHighlightColor(intensity);
          } else {
            // 默认颜色 - 根据深度使用渐变色
            this.ctx.fillStyle = this.getGradientColor(ball.z);
          }
          
          this.ctx.fillText(ball.skill, x, y);
          this.ctx.globalAlpha = 1;
        }
      }
    },
    
    getScale(z) {
      // 根据z坐标计算缩放比例，实现透视效果
      return this.depth / (this.depth + z);
    },
    
    getOpacity(z) {
      // 根据z坐标计算不透明度
      return 0.5 + (0.5 * (z + this.radius) / (this.radius * 2));
    },
    
    getTextSize(z) {
      // 根据z坐标计算文字大小
      const minSize = 10;
      const maxSize = 25;
      const normalizedZ = (z + this.radius) / (this.radius * 2); // 0-1
      return minSize + normalizedZ * (maxSize - minSize);
    },
    
    getGradientColor(z) {
      // 根据z坐标使用渐变色
      if (!this.useGradient) {
        return '#4361ee'; // 使用默认颜色
      }
      
      // 深度映射到0-1
      const t = (z + this.radius) / (this.radius * 2);
      
      // 颜色渐变 - 从深蓝到亮蓝
      const r = Math.round(64 + t * (67 - 64));
      const g = Math.round(97 + t * (130 - 97));
      const b = Math.round(237 + t * (238 - 237));
      
      return `rgb(${r}, ${g}, ${b})`;
    },
    
    getHighlightColor(intensity) {
      // 鼠标高亮颜色 - 从蓝色到金色
      const r = Math.round(67 + intensity * (245 - 67));
      const g = Math.round(97 + intensity * (197 - 97));
      const b = Math.round(238 - intensity * (238 - 66));
      
      return `rgb(${r}, ${g}, ${b})`;
    }
  }
}
</script>

<style scoped>
.skill-cloud-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.skill-cloud-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}

.skill-cloud-canvas:active {
  cursor: grabbing;
}
</style> 